#include <QtDebug>
#include <QtMath>
#include <cmath>
#include <math.h>
#include <stdexcept>
#include "qbciopacityrender.h"

// 波形生成部分
QElapsedTimer QWaveGeneratorInterface::mTimer;

void QWaveGeneratorInterface::init() { mTimer.start(); }
void QWaveGeneratorInterface::reset() { mTimer.start(); }

QWaveGeneratorInterface::QWaveGeneratorInterface() {}

double QWaveGeneratorInterface::value() { return funcOfTime(mTimer.elapsed()); }

QSinWaveGenerator::QSinWaveGenerator() : QWaveGeneratorInterface() {}

void QSinWaveGenerator::setFreq(const double &freq) {
  if (freq > 300) {
    throw "Frequence cannot larger than 300";
  }
  // 为了能够在改变频率时能够平滑地改变，因此
  // 需要根据时间、原频率以及新频率进行一次计算
  // 并且更新时间偏移量
  mPrePeriod = static_cast<long long>(1000 / mFreq);
  mFreq = freq;
  mNeedUpdate = true;
}

double QSinWaveGenerator::funcOfTime(const long long &t) {
  if (mNeedUpdate) {
    double cur = (t + mTimeBias) % mPrePeriod / static_cast<double>(mPrePeriod);
    long long curPeriod = static_cast<long long>(1000 / mFreq);
    mTimeBias = static_cast<long long>(cur * curPeriod) - t % curPeriod;
    mNeedUpdate = false;
  }
  return 0.5 * sin(2 * M_PI * mFreq *
                   (static_cast<double>((t + mTimeBias)) / 1000)) +
         0.5;
}

// 透明度闪烁部分
QBciOpacityRender::QBciOpacityRender()
{

}

void QBciOpacityRender::stylePaint(QPainter *painter)
{
    if (Wave && EnableWave) {
      painter->setOpacity(Wave->value());
    }
}

void QBciOpacityRender::setEnableWave(const bool &flag, const int &ID) {
  if (flag != EnableWave)
    Wave->reset();
  EnableWave = flag;
}

void QBciOpacityRender::setWaveType(WaveType w) {
    switch (w) {
    case sin:
        Wave = QSharedPointer<QSinWaveGenerator>::create();
        break;
    default:break;
    }
}

void QBciOpacityRender::setFreq(const int &ID, const double &freq) {
    Wave->setFreq(freq);
}

void QBciOpacityRender::startFlick() {
    if (Wave && !EnableWave) {
        EnableWave = true;
        setEnableWave(EnableWave);
    }
}

void QBciOpacityRender::stopFlick() {
    if (Wave && EnableWave) {
        EnableWave = false;
        setEnableWave(EnableWave);
    }
}
